After weeks of tweaking I finally gave up. I just couldn't fix my multiple file upload on safari, which really bothered me because my code worked perfectly as it should on other browsers, except on safari. Then I have just recently discovered that its not my code that has the problem. Its a Safari bug. Safari 5.1.+ can't read the html5 multiple attribute (or something like that). So users can't use the multiple upload feature, BUT, can properly upload a single file.
few links that discuss the issue:
https://github.com/moxiecode/plupload/issues/363
file input size issue in safari for multiple file selection
It seems that this bug has been around for quite some time. So I was wondering if there are workarounds available for this at the moment that some of you maybe are aware of? Because I can't find any. The only option available i found is to NOT use multiple attribute for Safari 5.1.+ users. Do you guys have any better ideas?
UPDATE
Safari 5.1.7 is the last version Apple made for the Windows OS. They did not continue to build current versions of Safari for Windows. Finding a fix for this bug for me is not necessary since Real Safari users are updated to the latest version of the browser(no facts), and just give a separate upload for those who are still using this outdated version, to not sacrifice the modern features of your application.
This is oldish question, but ... hack-type workaround is below.
Just remove multiple attribute for Safari, turnig it into MSIE<=9 little brother (non-XHR).
Rest of browsers will not be affected.
When Safari finally fixes problem, all you have to do is remove this hack::code and go back to standard input code.
here is standard input sample:
<input class="fileupload-input" type="file" name="files[]" multiple />
jQuery solution:
Just place it somewhere on a page, where you have files input tag.
you may read more here: How to detect Safari, Chrome, IE, Firefox and Opera browser?
$(document).ready(function () {
if (Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')>0);
$('.fileupload-input').removeAttr("multiple");
});
PHP solution
you will need some code to id browser I used a class I got one in github (MIT)
get it here: https://github.com/gavroche/php-browser
$files = '<input class="fileupload-input" type="file" name="files[]" multiple />';
if (Browser::getBrowser() === Browser::SAFARI) {
$files = '<input class="fileupload-input" type="file" name="files[]" />';
}
echo $files
That is all.
It seems that there is another issue that can be messing around. iOS Safari multiple file uploads always use the name "image.jpg" for all uploaded files. It may seem only one file uploaded in the server side but this is not what happened: it has been uploaded all files with the same name!
So, the workaround comes into the server side: just change the destination filename with a new generated name.
I am working with Flask and Python, so I use the standard formula.
@app.route("/upload",methods=['POST'])
def upload():
files = request.files.getlist('files[]')
for file in files:
if file and allowed_file(file.filename):
filename = generate_filename(file.filename)
file.save( os.path.join(app.config['UPLOAD_FOLDER'], new_album_id, filename))
return render_template('upload_ok.html')
Where generate_filaname
has to be a function that creates a new filename with the same extension as the original one. For example:
def generate_filename(sample_filename):
# pick up extension from sample filename
ext = sample_filename.split(".")[-1]
name = ''.join( random.SystemRandom().choice(string.letters+string.digits) for i in range(16) )
return name + "." + ext
The same can be done in PHP, of course.
I ran into the image.jpg problem with asp.net. It may benefit someone. I was appending a non-unique hash to each image file to tie it to the record in the db. Works fine on every platform (our users are using, anyway), except when using Safari. I just appended a hash and a unique three digit string I pulled from the seconds part of DateTime to string:
if (!string.IsNullOrEmpty(ViewState["HashId"].ToString()))
{
string filepath = Server.MapPath("~/docs/");
HttpFileCollection uploadedFiles = Request.Files;
Span1.Text = string.Empty;
for (int i = 0; i < uploadedFiles.Count; i++)
{
HttpPostedFile userPostedFile = uploadedFiles[i];
try
{
if (userPostedFile.ContentLength > 0)
{
string timestamp = DateTime.UtcNow.ToString("fff",
CultureInfo.InvariantCulture);
//Span1.Text += "<u>File #" + (i + 1) + "</u><br>";
//Span1.Text += "File Content Type: " + userPostedFile.ContentType + "<br>";
//Span1.Text += "File Size: " + userPostedFile.ContentLength + "kb<br>";
//Span1.Text += "File Name: " + userPostedFile.FileName + "<br>";
userPostedFile.SaveAs(filepath + "\\" + ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName));
// Span1.Text += "Location where saved: " + filepath + "\\" + Path.GetFileName(userPostedFile.FileName) + "<p>";
InsertFilename("~/docs/" + ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName), ViewState["HashId"] + "_" + Path.GetFileName(timestamp + userPostedFile.FileName));
}
}
catch (Exception Ex)
{
Span1.Text += "Error: <br>" + Ex.Message;
}
}
BindImages();
SetAttchBitTrue();
Button4.Visible = true;
AttchStatus.Text = "This Record Has Attachments";
Button2.Visible = true;
Button3.Visible = true;
Panel1.Visible = false;
}
May be a better way, but we just have a small number of people uploading one - two, maybe three images per record in the database. Should work.