Corrupted excel file when emailing it in Android from a Uri using the Gmail API.

huangapple go评论58阅读模式
英文:

Corrupted excel file when emailing it in Android from a Uri using the Gmail API

问题

I'm trying to share from Microsoft's Excel Android app to my custom Android app that will take the shared excel workbook and send it in an email through Gmail's API.

After my app sends the email and I try to open the excel file on my computer, I get there error, "We found a problem with some content in 'May 25.xlsx'."

It does, however, open in the desktop Chrome browser using Google Sheets.

Here's the Uri of the workbook: content://com.microsoft.office.excel.excelApplication.provider/docsui_temp_share_files/fea009cf-65c3-46f4-8dda-50758298b9fc/May%2025.xlsx

Here's the code that turns it into a file.

Context ctx; //defined by Android
Uri uri; //comes in populated with the value above
String filename; //generated from the Uri in a separate method

InputStream is = ctx.getContentResolver().openInputStream(uri);
File directory = ctx.getCacheDir();
FileOutputStream fos = null;
File fileToReturn = null;
try {
    final File tempFile = File.createTempFile(filename.split("\\.")[0], "." + filename.split("\\.")[1], directory);
    tempFile.deleteOnExit();

    fos = new FileOutputStream(tempFile);

    byte[] bytes = new byte[1024 * 16];
    int read = -1;
    while ((read = is.read(bytes)) != -1) {
        fos.write(bytes);
    }

    fileToReturn = tempFile;

}
finally {
    if (fos != null) {
        fos.close();
    }
}

Here's the code that creates the MimeMessage to send. The attachments parameter has the File created from above.

private MimeMessage createEmail(List<String> toAddresses,
                                String from,
                                String subject,
                                String bodyText, ArrayList<File> attachments) throws MessagingException {
    if(attachments == null){
        attachments = new ArrayList<>();
    }
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    MimeMessage email = new MimeMessage(session);
    InternetAddress fAddress = new InternetAddress(from);

    for(String toAddress : toAddresses) {
        InternetAddress toInternetAddress = new InternetAddress(toAddress);
        email.addRecipient(javax.mail.Message.RecipientType.TO, toInternetAddress );
    }

    email.setFrom(fAddress);
    email.setSubject(subject);

    Multipart multipart = new MimeMultipart();

    BodyPart textBody = new MimeBodyPart();
    textBody.setText(bodyText);
    multipart.addBodyPart(textBody);

    for (File attachment : attachments){
            MimeBodyPart attachmentBody = new MimeBodyPart();
            DataSource source = new FileDataSource(attachment.getAbsolutePath());
            attachmentBody.setDataHandler(new DataHandler(source));
            attachmentBody.setFileName(attachment.getName());
            multipart.addBodyPart(attachmentBody);
    }

    email.setContent(multipart);
    return email;
}

And the code to send the email.

private String sendMessage(Gmail service,
                           String userId,
                           MimeMessage email)
        throws MessagingException, IOException {

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    email.writeTo(bytes);

    ByteArrayContent messageByteArrayContent = new ByteArrayContent("message/rfc822", bytes.toByteArray());
    
    Message message;
    message = service.users().messages().send(userId, null, messageByteArrayContent).execute();
}

Here's what comes through as the email.

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----=_Part_0_262386509.1596398610889"
Date: Sun, 2 Aug 2020 13:03:34 -0700

------=_Part_0_262386509.1596398610889
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

May 252265647717182285060.xlsx
------=_Part_0_262386509.1596398610889
Content-Type: application/octet-stream; name="May 25.xlsx"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="May 25.xlsx"


------=_Part_0_262386509.1596398610889--

Note that the Content-Type is application/octet-stream.

I've made this application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, by manually adding a Content-Type header, but to no avail.

This code works to send almost anything else. And if I save the excel file first and share it from my file manager app, it opens just fine.

And it seems specific to an excel file. If I share it as a pdf from the Excel app (that's an option), the pdf opens fine.

I also encounter the same error if I try to share from the Google Sheets app, and share it as an .xlsx file. But again, if I try to share it as anything else, like a .csv or .pdf, it opens fine on the other side.

Here's the email if it's shared as a .pdf file from the Google Sheets app. Again, the content type is application/octet-stream, but it opens fine here.

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----=_Part_4_203349844.1596399067869"
Date: Sun, 2 Aug 2020 13:11:10 -0700

------=_Part_4_203349844.1596399067869
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Untitled spreadsheet8410545067288443069.pdf
------=_Part_4_203349844.1596399067869
Content-Type: application/octet-stream; name="Untitled spreadsheet8410545067288443069.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="Untitled spreadsheet8410545067288443069.pdf"


------=_Part_4_203349844.1596399067869--
英文:

I'm trying to share from Microsoft's Excel Android app to my custom Android app that will take the shared excel workbook and send it in an email through Gmail's API.

After my app sends the email and I try to open the excel file on my computer, I get there error, "We found a problem with some content in 'May 25.xlsx'."

It does, however, open in the desktop Chrome browser using Google Sheets.

Here's the Uri of the workbook: content://com.microsoft.office.excel.excelApplication.provider/docsui_temp_share_files/fea009cf-65c3-46f4-8dda-50758298b9fc/May%2025.xlsx

Here's the code that turns it into a file.

Context ctx; //defined by Android
Uri uri; //comes in populated with the value above
String filename; //generated from the Uri in a separate method

InputStream is = ctx.getContentResolver().openInputStream(uri);
File directory = ctx.getCacheDir();
FileOutputStream fos = null;
File fileToReturn = null;
try {
    final File tempFile = File.createTempFile(filename.split(&quot;\\.&quot;)[0], &quot;.&quot; + filename.split(&quot;\\.&quot;)[1], directory);
    tempFile.deleteOnExit();

    fos = new FileOutputStream(tempFile);

    byte[] bytes = new byte[1024 * 16];
    int read = -1;
    while ((read = is.read(bytes)) != -1) {
        fos.write(bytes);
    }

    fileToReturn = tempFile;

}
finally {
    if (fos != null) {
        fos.close();
    }
}

Here's the code that creates the MimeMessage to send. The attachments parameter has the File created from above.

private MimeMessage createEmail(List&lt;String&gt; toAddresses,
                                String from,
                                String subject,
                                String bodyText, ArrayList&lt;File&gt; attachments) throws MessagingException {
    if(attachments == null){
        attachments = new ArrayList&lt;&gt;();
    }
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    MimeMessage email = new MimeMessage(session);
    InternetAddress fAddress = new InternetAddress(from);

    for(String toAddress : toAddresses) {
        InternetAddress toInternetAddress = new InternetAddress(toAddress);
        email.addRecipient(javax.mail.Message.RecipientType.TO, toInternetAddress );
    }

    email.setFrom(fAddress);
    email.setSubject(subject);

    Multipart multipart = new MimeMultipart();

    BodyPart textBody = new MimeBodyPart();
    textBody.setText(bodyText);
    multipart.addBodyPart(textBody);

    for (File attachment : attachments){
            MimeBodyPart attachmentBody = new MimeBodyPart();
            DataSource source = new FileDataSource(attachment.getAbsolutePath());
            attachmentBody.setDataHandler(new DataHandler(source));
            attachmentBody.setFileName(attachment.getName());
            multipart.addBodyPart(attachmentBody);
    }

    email.setContent(multipart);
    return email;
}

And the code to send the email.

private String sendMessage(Gmail service,
                           String userId,
                           MimeMessage email)
        throws MessagingException, IOException {

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    email.writeTo(bytes);

    ByteArrayContent messageByteArrayContent = new ByteArrayContent(&quot;message/rfc822&quot;, bytes.toByteArray());
    
    Message message;
    message = service.users().messages().send(userId, null, messageByteArrayContent).execute();
}

Here's what comes through as the email.

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=&quot;----=_Part_0_262386509.1596398610889&quot;
Date: Sun, 2 Aug 2020 13:03:34 -0700

------=_Part_0_262386509.1596398610889
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

May 252265647717182285060.xlsx
------=_Part_0_262386509.1596398610889
Content-Type: application/octet-stream; name=&quot;May 25.xlsx&quot;
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=&quot;May 25.xlsx&quot;


------=_Part_0_262386509.1596398610889--

Note that the Content-Type is application/octect-stream.

I've made this application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, by manually adding a Content-Type header, but to no avail.

This code works to send almost anything else. And if I save the excel file first and share it from my file manager app, it opens just fine.

And it seems specific to an excel file. If I share it as a pdf from the Excel app (that's an option), the pdf opens fine.

I also encounter the same error if I try to share from the Google Sheets app, and share it as an .xlsx file. But again, if I try to share it as anything else, like a .csv or .pdf, it opens fine on the other side.

Here's the email if it's shared as a .pdf file from the Google Sheets app. Again, the content type is application/octet-stream, but it opens fine here.

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=&quot;----=_Part_4_203349844.1596399067869&quot;
Date: Sun, 2 Aug 2020 13:11:10 -0700

------=_Part_4_203349844.1596399067869
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Untitled spreadsheet8410545067288443069.pdf
------=_Part_4_203349844.1596399067869
Content-Type: application/octet-stream; name=&quot;Untitled spreadsheet8410545067288443069.pdf&quot;
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=&quot;Untitled spreadsheet8410545067288443069.pdf&quot;


------=_Part_4_203349844.1596399067869--

答案1

得分: 1

在代码中,您在编写xlsx文件时,总是读取指定的缓冲区大小(1024 * 16),然后写入文件。我认为在最后一次读取时,如果您读取的字节数少于字节数组的缓冲区大小,那么您将写入多余的不必要字节。这可能是导致文件损坏的原因。

英文:

In the code, where you are writing the xlsx file, you are always reading a specified buffer size (1024 * 16), and writing to file. I think on last read, if the bytes you read are less than the buffer size of your bytes array, you would be writing extra unnecessary bytes. This could be your file corruption reason.

huangapple
  • 本文由 发表于 2020年8月3日 04:38:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/63220788.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定