- PR -

ActiveReportsNET2で指定のフォルダにPDFを生成したものを置く方法

1
投稿者投稿内容
貧乏人
会議室デビュー日: 2007/02/15
投稿数: 17
投稿日時: 2007-04-07 02:13
いつも参考にさせて頂いています、貧乏人です。

現在C#とActiveReportsNET2を利用してWeb上から一括バッチを起動する処理を
製造しておりまして、現行で動作している下記にて帳票出力する既存処理を
ちょろっと変更(参考)して任意のディレクトリにPDF形式のファイルを置きたい処理
(ダウンロードダイアログなどをつけずにPDFファイルを作成する処理)
を作成しようとしているのですがうまくいきません。

try {
// レポートオブジェクトを生成します。
ActiveReport report = (ActiveReport)System.Activator.CreateInstance(cls);

// レポートレイアウトファイルを読み込みレポートを作成します。
if(data==null){
data = new DataTable();
}
if (report is ActiveReportBase && sd !=null )
{
ActiveReportBase arb = (ActiveReportBase)report;
arb.Attributes = sd;
arb.LoadAttributes();
}
report.DataSource = data;
report.Run();

// PDFのMETA情報設定
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "inline; filename=" + cls.ToString() + ".PDF");

// 出力部品生成
System.IO.MemoryStream memStream = new System.IO.MemoryStream();
PdfExport xpdf = new PdfExport();

// 指定のフォルダにPDFファイルをエクスポートします。
xpdf.Export(report.Document, memStream);
Response.BinaryWrite(memStream.ToArray());
}
catch (Exception exx)
{
// エラーが発生した場合、メッセージを表示します。
Response.Write(" exportPDF DF作成時にエラーが発生しました。\n"+exx.ToString());
return false; // レポートの生成に失敗した場合は、処理を中断。
}
return true; // 正常処理

PdfExportやMemoryStreamあたりの各種メソッドの引数にパスを
指定したりと色々と試しているのですが中々うまくいきません。

どなたかアドヴァイス・御知恵を拝借したい所存で御座います。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-04-07 09:45
引用:

貧乏人さんの書き込み (2007-04-07 02:13) より:

現在C#とActiveReportsNET2を利用してWeb上から一括バッチを起動する処理を製造しておりまして、現行で動作している下記にて帳票出力する既存処理をちょろっと変更(参考)して任意のディレクトリにPDF形式のファイルを置きたい処理(ダウンロードダイアログなどをつけずにPDFファイルを作成する処理)を作成しようとしているのですがうまくいきません。


ダウンロード ダイアログ... ということはクライアントに保存したいのですか。
だとすれば、セキュリティ上無理ですね。
ActiveX か何かをクライアント側に入れてもらうくらいしか思いつきません。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
貧乏人
会議室デビュー日: 2007/02/15
投稿数: 17
投稿日時: 2007-04-09 09:06
じゃんぬねっとさん、ありがとうございます。

こちらのファイルの保存は、
クライアントサイドでは無く、サーバの任意のフォルダにPDFファイルを
保存したいと考えております。

Streamインターフェースから派生する子クラスを使用して
色々試していますが、中々うまくいかない状況です。。。
貧乏人
会議室デビュー日: 2007/02/15
投稿数: 17
投稿日時: 2007-04-09 10:11
Streamはインターフェースで無く抽象クラスでした、。

System.IO.MemoryStream上で(メモリ上)で展開されたファイルを
System.IO.FileStreamなどを利用して
指定のディレクトリに出力することなどはできるのでしょうか?
(MemoryStream⇔FileStreamにて互換性があるのでしょうか?)

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=9594&forum=7&start=8
↑こちらを見るとなんとなくできそうな気はして、
msdnとソース上で格闘しているのですが、、、、。
かめたろ
ぬし
会議室デビュー日: 2003/03/20
投稿数: 255
投稿日時: 2007-04-09 10:31
引用:

貧乏人さんの書き込み (2007-04-07 02:13) より:
// 指定のフォルダにPDFファイルをエクスポートします。
xpdf.Export(report.Document, memStream);
Response.BinaryWrite(memStream.ToArray());


この部分、クライアントにバイナリを渡そうとしてますよね。
サーバの任意のフォルダにPDFファイルを保存したいのなら、ストリームをファイルに書き出すだけでいいような気がしますが。MemoryStreamを一旦バイト配列に書き出して、それをFileStreamでファイルに書くってかんじでしょうか。

提示のコードを見る限りではPDFをダウンロードさせようとしてるように見受けられるので、外してるかも。
貧乏人
会議室デビュー日: 2007/02/15
投稿数: 17
投稿日時: 2007-04-09 11:29
かめたろさん、大変ありがとうございます。

早速ご参考まで下記処理を施しました。

// 出力部品生成
System.IO.MemoryStream memStream = new System.IO.MemoryStream();

PdfExport xpdf = new PdfExport();

// 指定のフォルダにPDFファイルをエクスポートします。
xpdf.Export(report.Document, memStream);
// Response.BinaryWrite(memStream.ToArray());
// (上記までは正常に動作します。。。)
// メモリストリームよりバイト配列取得をする。
byte[] buf = memStream.GetBuffer();
string fileName = @"C:\test.pdf";

// ファイルを開く
System.IO.FileStream fiStream =
new System.IO.FileStream(fileName,
System.IO.FileMode.Create,
System.IO.FileAccess.Write);
// バイト型配列の内容書込み
fiStream.Write(buf, 0, buf.Length);
// ファイルストリームのクローズ
fiStream.Close();

上記処理を実装したところ、
System.UnauthorizedAccessException: パス 'C:\test.pdf' へのアクセスが拒否されました。
場所 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
場所 System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
場所 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)

そもそも指定のファイルが存在しておらず、
そちらが問題かと思うのですが、
System.IO.FileMode.Createを指定しているので問題無いと
認識しているのですが、、、。
知識不足で恥ずかしい限りで、恐縮な限りですが
上記(ファイル出力)にて御教授頂けないでしょうか?
ぽぴ王子
ぬし
会議室デビュー日: 2006/03/24
投稿数: 475
お住まい・勤務地: お住まい:城・勤務地:城
投稿日時: 2007-04-09 11:53
引用:

貧乏人さんの書き込み (2007-04-09 11:29) より:

上記処理を実装したところ、
System.UnauthorizedAccessException: パス 'C:test.pdf' へのアクセスが拒否されました。
場所 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
場所 System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
場所 System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)

そもそも指定のファイルが存在しておらず、
そちらが問題かと思うのですが、
System.IO.FileMode.Createを指定しているので問題無いと
認識しているのですが、、、。


んーと、知識不足というのは確かにあるかもしれませんが、読んで字のご
とくということもあると思います。
せっかくエラーメッセージに
> パス 'C:test.pdf' へのアクセスが拒否されました。
とあるわけで、原因はアクセスが拒否されたことに他なりません。
ではなぜアクセスが拒否されたのか、というのは知識が必要なので、そこ
は知識不足といっても差し支えないとは思いますが…

この場合、IIS が動作しているユーザ( "ASPNET" だったり "Network
Service" だったりと、この辺はバージョンによっても変わってきます)に、
該当するディレクトリへの書き込み権限を与えてあげることが必要になると
思います。

コード:

	// 出力部品生成
	System.IO.MemoryStream memStream	= new System.IO.MemoryStream();

	PdfExport xpdf = new PdfExport();

	// 指定のフォルダにPDFファイルをエクスポートします。
	xpdf.Export(report.Document, memStream);
//	Response.BinaryWrite(memStream.ToArray());
// (上記までは正常に動作します。。。)
	// メモリストリームよりバイト配列取得をする。
	byte[] buf		= memStream.GetBuffer();
	string fileName	= @"C:\test.pdf";


PdfExport.Export メソッドの二番目の引数はストリームを渡してやるの
で、MemoryStream から一旦バイト配列にしなくても、そのまま
FileStream を渡してあげれば大丈夫だと思います。
MemoryStream に渡しているのは、それをクライアントにダウンロードさ
せるためだったからですね。
_________________
ぽぴ王子@わんくま同盟
ぽぴ王子の人生プログラミング中 / ぽぴンち。
貧乏人
会議室デビュー日: 2007/02/15
投稿数: 17
投稿日時: 2007-04-09 14:21
ぽぴ王子、ありがとうございます。

IISに該当する権限を付与しましたらPDFファイルが作成されました。
私の本件の根本の問題は、ディレクトリへの書き込み権限が原因していたようで、
エラー内容を当方で捉え違えたようでした。。

サーバサイドの指定のフォルダへ直接ファイルを作成する場合であれば、
王子(多分、おうちが近いと思われます)のアドヴァイスの通り、
直接FileStreamオブジェクトを引渡す形で問題ありませんでした。

// 出力部品生成
string fileName = @"C:\" + cls.ToString() + ".PDF";

// ファイルを開く
System.IO.FileStream fiStream =
new System.IO.FileStream(fileName,
System.IO.FileMode.Create,
System.IO.FileAccess.Write);

PdfExport xpdf = new PdfExport();

// 指定のフォルダにPDFファイルをエクスポートします。
xpdf.Export(report.Document, fiStream);

// ファイルストリームのクローズ
fiStream.Close();

上記にて問題ありませんでした。

大変、参考になりました。本当にありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)